﻿using Microsoft.AspNetCore.Mvc.Filters;
using SimpleX.RBAC;
using System.Net;

namespace SimpleX
{
    /// <summary>
    /// 
    /// </summary>
    public class ActionFilter : IAsyncActionFilter
    {
        /// <summary>
        /// jwt验证通过或者匿名接口执行进行接口验证
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var httpContext = context.HttpContext;
            var allowAnonymous = context.ActionDescriptor.EndpointMetadata.OfType<AllowAnonymousAttribute>().Any();

            if (allowAnonymous)
            {
                await next();
                return;
            }

            var httpStatus = await CheckPermission(httpContext);
            if (httpStatus != HttpStatusCode.OK)
            {
                var apiResponse = new UnifyResult<object>
                {
                    Code = httpStatus,
                    Exts = Unify.Read(),
                    Msg = "Access Denied / 拒绝访问",
                    Timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
                };

                context.Result = new ObjectResult(apiResponse)
                {
                    StatusCode = (int?)apiResponse.Code,
                    DeclaredType = typeof(UnifyResult<object>)
                };
                return;
            }

            await next();
        }

        /// <summary>
        /// 权限检查通过 200，无权限403 ,Token被吊销 401
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        private async Task<HttpStatusCode> CheckPermission(HttpContext httpContext)
        {
            //检查token是否在redis中,方便吊销token
            var token = httpContext.GetToken();
            var tokenInRedis = App.ServiceProvider.GetService<IAuthService>().CheckTokenInRedis(token);
            if (!tokenInRedis)
            {
                return HttpStatusCode.Unauthorized;
            }

            //超级管理员能访问所有接口
            if (UserManager.SuperAdmin)
                return HttpStatusCode.OK;

            var isSpuerAdmin = httpContext.GetMetadata<SuperAdminAttribute>();
            if (isSpuerAdmin != null) //如果是超级管理员才能访问的接口
            {
                //获取忽略超级管理员特性
                var ignoreSpuerAdmin = httpContext.GetMetadata<IgnoreSuperAdminAttribute>();
                if (ignoreSpuerAdmin == null && !UserManager.SuperAdmin) //如果只能超级管理员访问并且用户不是超级管理员
                    return HttpStatusCode.Forbidden;
            }

            //获取角色授权特性
            var isRolePermission = httpContext.GetMetadata<RolePermissionAttribute>();
            if (isRolePermission != null)
            {
                //获取忽略角色授权特性
                var ignoreRolePermission = httpContext.GetMetadata<IgnoreRolePermissionAttribute>();
                if (ignoreRolePermission == null)
                {
                    // 路由名称
                    var routeName = httpContext.Request.Path.Value;
                    //获取用户信息
                    var codes = await App.ServiceProvider.GetService<ISysUserService>().OwnPermissionCodeList();
                    if (codes == null || !codes.Contains(routeName)) //如果当前路由信息不包含在角色授权路由列表中则认证失败
                        return HttpStatusCode.Forbidden;
                }
            }
            return HttpStatusCode.OK;
        }
    }
}